package com.isias.system.service.Impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.isias.common.result.ResultCodeEnum;
import com.isias.common.util.JwtHelper;
import com.isias.common.util.MD5;
import com.isias.model.system.SysUser;
import com.isias.model.system.SysUserRole;
import com.isias.model.vo.LoginVo;
import com.isias.model.vo.RouterVo;
import com.isias.model.vo.SysUserQueryVo;
import com.isias.system.Util.EmailUtil;
import com.isias.system.Util.RandomCaptchaUtile;
import com.isias.system.handler.GeneralException;
import com.isias.system.handler.LoginException;
import com.isias.system.mapper.SysUserMapper;
import com.isias.system.mapper.SysUserRoleMapper;
import com.isias.system.service.SysMenuService;
import com.isias.system.service.SysUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author fanyi
 * @since 2023-02-19
 */
@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    @Autowired
    SysUserMapper sysUserMapper;
    @Autowired
    SysMenuService sysMenuService;

    @Autowired
    SysUserRoleMapper sysUserRoleMapper;

    @Autowired
    private RandomCaptchaUtile randomCaptchaUtile;

    @Autowired
    private EmailUtil emailUtil;

    @Override
    public IPage<SysUser> SeletePage(Page<SysUser> page, SysUserQueryVo sysUserQueryVo) {
        return sysUserMapper.selectPage(page, sysUserQueryVo);
    }

    @Override
    public Boolean updataStatus(String id, Integer status) {
        Integer integer = sysUserMapper.updataStatus(id, status);
        if (integer == 1){
            return true;
        }else {
            return false;
        }
    }

    /**
     * 登录
     * 返回token
     * */
    @Override
    public Map<String, Object> Login(LoginVo loginVo) {
        Map<String, Object> map = new HashMap<>();
//        LambdaQueryWrapper<SysUser> lqw = new LambdaQueryWrapper<>();
//        /**查询数据库中是否有用户信息*/
//        /* 判断是否为空，虽然lqw也能判断，但是如果为空的话,loginVo.getUsername()就会报错，所以选择把if抽取出来 */
//        if (loginVo!=null){
//            lqw.eq(SysUser::getUsername,loginVo.getUsername());
//        }else {
//            throw new LoginException(ResultCodeEnum.ILLEGAL_REQUEST);   //非法请求
//        }
        if (loginVo == null){
            throw new LoginException(ResultCodeEnum.ILLEGAL_REQUEST);   //非法请求
        }
        //校验账号
        SysUser user=null;
        user = sysUserMapper.selectUser(loginVo.getUsername());
        if (user == null){
            throw new LoginException(ResultCodeEnum.ACCOUNT_ERROR);     //账号不正确
        }
        /**核对密码*/
        //由于数据库密码经过MD5加密，所以此处也对登录的密码进行MD5加密后与数据库对比，并进行取反操作便于使用if语句
        if (!user.getPassword().equals(MD5.encrypt(loginVo.getPassword()))) {
            throw new LoginException(ResultCodeEnum.PASSWORD_ERROR);     //密码不正确
        }
        /**查看账户启用状态*/       //1为启用，0为弃用
        if (user.getStatus().intValue() == 0) {
            throw new LoginException(ResultCodeEnum.ACCOUNT_STOP);     //账号停用
        }
        /**通过用户id和用户名生成token放入Map集合里返回前端*/        //后期还可以把token存进Redis做一个双重验证
        map.put("token", JwtHelper.createToken(user.getId(),user.getUsername()));
        return map;
    }

    /**
     * 获取用户信息
     * */
    @Override
    public Map<String, Object> getUserInfo(String username) {
        Map<String, Object> resultmap = new HashMap<>();
        LambdaQueryWrapper<SysUser> infolqw = new LambdaQueryWrapper<>();
        //通过username查询到用户所有的信息
        infolqw.eq(SysUser::getUsername,username);
        SysUser sysUser = sysUserMapper.selectOne(infolqw);
        //根据userid查询菜单权限值
        List<RouterVo> routerVoList = sysMenuService.getUserMenuList(sysUser.getId());
        //根据userid查询按钮权限值
        List<String> permsList = sysMenuService.getUserButtonList(sysUser.getId());

        resultmap.put("roles","[admin]");
        resultmap.put("name",sysUser.getName());
        resultmap.put("avatar",sysUser.getHeadUrl());
        resultmap.put("buttons", permsList);
        resultmap.put("routers", routerVoList);

        return resultmap;
    }

    /**
     * 更新用户头像地址
     * @param url
     * @return
     */
    @Override
    public Boolean updataHeadUrl(String username,String url) {
        return sysUserMapper.updataUrl(username,url);
    }

    /**
     * 添加用户-顺带分配权限
     * @param sysUser
     * @return
     */
    @Override
    public boolean saveUser(SysUser sysUser) {
        if (sysUserMapper.insert(sysUser) == 0) {
            return false;
        }
        SysUserRole sysUserRole = new SysUserRole();
        sysUserRole.setUserId(sysUser.getId());
        sysUserRole.setRoleId("2");     //管理员创建默认为学生，自己注册默认为游客
        if (sysUserRoleMapper.insert(sysUserRole) == 0) {
            return false;
        }

        return true;
    }

    /**
     * 从外部注册账户
     * @param sysUser
     * @return
     */
    @Override
    public boolean register(SysUser sysUser) {
        /*判断数据库中有没有相同的用户名和手机号*/
        SysUser User= null;
        User = sysUserMapper.selectUser(sysUser.getUsername());
        if (User != null){
            throw new GeneralException(ResultCodeEnum.ALREADY_EXISTS);
        }
        User = sysUserMapper.selectUserphone(sysUser.getPhone());
        if (User != null){
            throw new GeneralException(ResultCodeEnum.REPEAT_PHONE);
        }
        /*判断验证码是否正确*/
        String rediscode = randomCaptchaUtile.getcode(sysUser.getEmail());
        if (! sysUser.getCaptchacode().equals(rediscode)) {
            throw new GeneralException(ResultCodeEnum.CAPTCHA_ERROR);
        }
        /*插入，并分配游客角色*/
        sysUser.setPassword(MD5.encrypt(sysUser.getPassword()));    //密码进行加密处理
        if (sysUserMapper.insert(sysUser)==0) {
            return false;
        }
        SysUserRole sysUserRole = new SysUserRole();
        sysUserRole.setUserId(sysUser.getId());
        sysUserRole.setRoleId("4");     //自己注册默认为游客
        if (sysUserRoleMapper.insert(sysUserRole) == 0) {
            return false;
        }
        return true;
    }

    /**
     * 生成验证码
     *
     * @param email
     * @return
     */
    @Override
    @CachePut(value = "DodoCaptcha",key = "#email")
    public String GetCode(String email) {
        String captcha = randomCaptchaUtile.generator(email);
        String title = "卷死其他组教学管理系统注册账户验证码";
        String content = "您好，"+email+"您的验证码为"+captcha+",请在五分钟内进行验证，验证失败请联系客服：19138060480";
        log.info("有用户注册，验证码为："+captcha+",邮箱号为："+email);
        emailUtil.sendMessage(email, title, content);
        return captcha;
    }

    @Override
    public SysUser GetUserByusername(String username) {
        return sysUserMapper.selectUser(username);
    }

    @Override
    public String GetIdByUsername(String username) {
        return sysUserMapper.GetIdByUsername(username);
    }

    @Override
    public boolean savePost(String id, String postid) {
        return sysUserMapper.updatePostId(id,postid) > 0;
    }

    @Override
    public boolean doAssign(String userId, String deptId) {
        return sysUserMapper.updateDeptId(userId,deptId) > 0;
    }

    @Override
    public boolean CodeIsRight(String email,String code) {
        String rediscode = randomCaptchaUtile.getcode(email);
        if (rediscode.equals(code)) {
            return true;
        }
        return false;
    }

    @Override
    public boolean UpdatePassword(String username, String password) {
        String newPassword = MD5.encrypt(password);
        if (sysUserMapper.UpdatePassword(username,newPassword)>0) {
            return true;
        }
        return false;
    }

    @Override
    public boolean PasswordIsRight(String username, String password) {
        SysUser user=null;
        user = sysUserMapper.selectUser(username);
        /**核对密码*/
        //由于数据库密码经过MD5加密，所以此处也对登录的密码进行MD5加密后与数据库对比，并进行取反操作便于使用if语句
        if (user.getPassword().equals(MD5.encrypt(password))) {
            return true;
        }
        return false;
    }

}
